MBA em Ciência de Dados

Técnicas Avançadas de Captura e Tratamento de Dados

Avaliação Final

Aluno: Rafael Capaci Pereira

Professores: Luis Gustavo Nonato e Moacir Antonelli Ponti

Cemeai - ICMC/USP São Carlos

A avaliação vale 10 pontos. As questões de 1 a 4, caso respondidas da forma correta, já totalizam 10 pontos.

**ATENÇÃO:**

Bibliotecas a serem instaladas:

Questão 1 (2.5 pontos)

Considere o arquivo modcovid.pdf (disponível para download no moodle). Escreva um código para extrair o texto (ASCII) do arquivo PDF e escreva o texto extraído em um arquivo chamado modcovid.txt.

Para resolver a questão, foram desenvolvidas as funções convert_pdf_to_string e write_string_to_file. O arquivo .pdf é lido como imagem e o conteúdo de todas as páginas é retornado como uma string.

Questão 2 (2.5 pontos)

Leia o arquivo modcovid.txt e realize as seguinte operações:

  1. Extraia todas palavras contidas no arquivo e armazene em uma lista de palavras (utilize o método word_tokenize do pacote nltk).

  2. Remova da lista de palavras todas as "palavras" que não sejam formadas exclusivamente de caracteres do alfabeto.

  3. Quantas palavras com apenas 1 caractere sobraram na lista?

Desenvolvimento da resposta

A função get_tokens_from_file lê um arquivo e extrai as palavras do texto, retornando-as em uma lista através da função word_tokenize, do pacote nltk

A função abaixo remove todas as palavras que não são formadas exclusivamente por caracteres alfanuméricos

A próxima função filtra as palavras de uma lista pelo tamanho

A seguir, as três funções declaradas anteriormente são executadas, lendo o arquivo modcovid.txt, removendo as palavras não alfanuméricas e por fim, filtrando as palavras de tamanho 1, de modo a responder a terceira pergunta.

Ao executar esses passos, observa-se que o número de palavras de tamanho 1 é 44


Questão 3 (2.5 pontos)

Carregue o arquivo artists_mba21.csv e armazene em um pandas DataFrame.

Esse arquivo possui os atributos:

3.a (1.5 pontos)

Exiba um histograma contendo a frequência dos diferentes gêneros dos artistas. Note que um artista pode ter mais do que um gênero associado.

Dica: use a função str.split(',') para separar múltiplos gêneros

Desenvolvimento da resposta

Podemos verificar que na coluna genre, os dados estão dentro de uma string, onde os gêneros de um artista são separados por vírgula.

Inicialmente, o método str.split() é utilizado para converter cada string em um array contendo os gêneros.

Como estamos interessados somente na frequência dos gêneros, utilizaremos o método explode para "concatenar" todas as listas em uma nova série do pandas.

A partir da série genres montamos o gráfico de barras com as frequências de cada gênero, ordenadas de maneira decrescente.

3.b (1.0 ponto)

Trate a coluna "paintings", a qual deveria conter apenas atributos numéricos inteiros.

Siga os seguintes passos:

  1. Exiba os valores não convertíveis para númerico
  2. Converta a coluna para o tipo inteiro de forma que não haja dados perdidos/faltantes

Após o tratamento exiba a estatística descritiva da coluna tratada usando describe()

Dica: há várias soluções possíveis, mas usar expressões regulares pode ser útil nesse caso. Por exemplo a expressão '(\d+)' extrai apenas dígitos

Desenvolvimento da resposta

Primeiramente, vamos verificar quais são os valores possíveis da coluna, para entender se há muitos valores errôneos

Podemos observar que praticamente todos os valores são formados por números, com poucos erros, às vezes alguns caracteres junto com os valores numéricos, como parênteses ou aspas. Além desse tipo de valor, existe o valor "three", que é o número 3 por extenso em inglês. Como é um caso único, podemos corrigir esse valor diretamente, mantendo-o como uma string, para corresponder com o tipo dos outros valores:

Agora podemos tratar os outros casos.

Primeiramente, vamos extrair os valores numéricos de cada linha da nossa coluna, utilizando o método extract com a expressão regular (\d+)

Observando novamente os valores da coluna, é possível ver que temos somente os valores numéricos, porém ainda como strings

Então convertemos esses valores para numéricos, de forma que seja possível avaliar as estatisticas descritivas da coluna

Questão 4 (2.5 pontos)

Dada uma imagem query.jpg de uma pintura da qual não sabemos o artista, gostaríamos de fazer uma busca numa base de dados e recuperar obras similares de acordo com suas cores. Para isso utilizaremos um descritor baseado em cores conhecido por Border-Interior Classification (BIC)

Stehling, R. O., Nascimento, M. A., & Falcão, A. X. (2002). A compact and efficient image retrieval approach based on border/interior pixel classification. In Proceedings of the eleventh international conference on Information and knowledge management (pp. 102-109).

O BIC funciona da seguinte forma:

  1. Transforma a imagem em um único canal de cores
  2. Reescala o número de cores da imagem para $C$ cores
  3. Computa dois histogramas de cor na imagem:
    1. Para os pixels considerados "interior", cuja cor seja igual à dos 4 vizinhos (cima, baixo, direita e esquerda)
    2. Para todos os pixels da imagem, considerados de "borda". Aqui também entram os pixels na extremidade da imagem (ou seja as primeiras e últimas linhas/colunas)
  4. Normaliza cada histograma, concatena os histogramas em um único vetor e normaliza novamente o vetor concatenado

Exemplo seja a matriz abaixo uma imagem com $C=4$, ou seja, com cores 0, 1, 2 e 3:

3 3 3 2 2 0
3 3 3 2 2 2
3 3 3 2 2 2
3 3 3 3 2 2
0 3 3 1 2 0

Os valores em negrito correspondem à cores "interior" e o restante de "borda".

Assim, teríamos o seguintes histogramas:
h_borda = [3,1,9,11]
h_inter = [0,0,2,4]

Note que cada vetor representa as frequências, em ordem, das cores 0, 1, 2 e 3. Por exemplo, há 3 pixels da cor 0 referentes à borda, há 2 pixels da cor 2 referentes a interior.

Após computar os histogramas, é preciso normalizá-los para evitar problemas com imagens de diferentes resoluções. Diferentes métodos podem ser utilizados. Aqui utilizaremos a normalização L1, dividindo os elementos pela soma absoluta do vetor, resultando em:
h_borda_nr = [0.125, 0.0417, 0.375, 0.4583]
h_inter_nr = [0.000, 0.0000, 0.333, 0.6667]

Assim, para uma determinada imagem com $C$ cores, o vetor de características terá $2\cdot C$ dimensões, relativas aos 2 histogramas concatenados. Após a concatenação normalizamos novamente:
bic_norm = [0.0625, 0.0208, 0.1875, 0.2292, 0.0000, 0.0000, 0.1667, 0.3333]

Esse será o vetor de características final a ser utilizado


Use o descritor BIC com $C=32$ para as imagens disponibilizadas. Use a função disponibilizada rescale_image_colors() para reescalar a imagem.

Faça uma busca no diretório paintings21, retornando as 5 imagens mais similares a query.jpg de acordo com o descritor BIC e a distância Euclidiana. Exiba a imagem de consulta, e também as 5 imagens retornadas, com seus nomes e valores da distância obtidos.

Desenvolvimento da resposta

Inicialmente, é definida a função bic juntamente com algumas funções auxiliares de modo a implementar o algoritmo BIC, especificado acima.

Em seguida, vamos ler a imagem de consulta e guardá-la no dicionário query_image.

Todas as imagens serão guardadas num dicionário com a mesma estrutura, contendo as seguintes chaves:

As características da imagem, extraídas pela função bic, serão armazenada na variável query_features para, futuramente, ser comparada com as outras imagens

Agora vamos ler todas as outras imagens do diretório e armazená-las em uma estrutura idêntica a da imagem de consulta, dentro da lista images.

Aqui as características das imagens também são extraídas, porém, serão armazenadas na variável images_features, que mais tarde será convertida para uma matriz do numpy. Armazená-las nessa estrutura nos permite calcular as distâncias de maneira vetorizada, otimizando o código.

Calculando as distâncias

A função k_nearest_indexes_and_distances calcula a distância euclidiana e retorna os k indices das imagens mais próximas, bem como as respectivas distâncias.

As imagens mais próximas são recuperadas a partir do seu índice e armazenadas na variável nearest_images

Exibindo as imagens

A seguir, as imagens são exibidas. A primeira é a imagem de consulta e as seguintes são as mais próximas, em ordem.

A imagem de consulta é concatenada no início das imagens mais próximas, bem como o valor 0 é concatenado as distâncias, permitindo que todas as imagens sejam exibidas no mesmo laço.